import axios, {
    AxiosInstance,
    AxiosRequestConfig,
    Canceler,
    AxiosResponse,
  } from 'axios';
  
  /**
   * http请求v2版本拦截器
   * @param axiosInstance axios请求实例
   * @param requestStack 请求栈
   */
  export const InterceptorV2 = (
    axiosInstance: AxiosInstance,
    requestStack: AxiosRequestConfig[] = [],
  ) => {
    // 添加请求拦截器
    axiosInstance.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        // 阻断请求方法
        let cancelRequest: any = () => {};
        config.cancelToken = new axios.CancelToken(
          (cancel: Canceler) => (cancelRequest = cancel),
        );
        // 这里判断当前请求是否需要阻断
        const needStop = false;
        if (needStop || isRequestRepeat(requestStack, config, 'request') !== -1) {
          cancelRequest('请求重复被阻止');
        } else {
          requestStack.push(config);
        }
        return config;
      },
      (error) => {
        return Promise.reject(error);
      },
    );
    // 添加响应拦截器
    axiosInstance.interceptors.response.use(
      (response: AxiosResponse) => {
        // 删除请求栈里的请求配置
        const { config } = response;
        requestStack.splice(isRequestRepeat(requestStack, config, 'response'), 1);
        return response;
      },
      (error: { response: AxiosResponse }) => {
        if (error.response) {
          const { status } = error.response;
          switch (status) {
            case 400:
              console.log('400啦');
              break;
            case 401:
              // 处理token失效逻辑
              console.log('401啦');
              break;
            default:
              break;
          }
        }
        return Promise.reject(error);
      },
    );
  };
  
  /**
   * 判断请求是否重复
   * @param requestStack 请求队列
   * @param requestConfig 请求实例配置
   */
  export const isRequestRepeat = (
    requestStack: Array<AxiosRequestConfig>,
    requestConfig: AxiosRequestConfig,
    type: string,
  ): number => {
    const { method, params, data, url } = requestConfig;
    return requestStack.findIndex((op: AxiosRequestConfig) => {
      const methodType =
        method?.toLocaleUpperCase() === op.method?.toLocaleUpperCase();
      const urlType = url === op.url;
      const propsType =
        method?.toLocaleUpperCase() === 'POST'
          ? diff(data, op.data)
          : diff(params, op.params);
      return methodType && urlType && propsType;
    });
  };
  
  /**
   * 判断两个对象是否相同
   * @param obj1
   * @param obj2
   */
  export const diff = (obj1: object, obj2: object) => {
    let resultType: boolean = true;
    if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;
    Object.keys(obj1).forEach((key) => {
      if (typeof Reflect.get(obj1, key) === 'object') {
        if (!diff(Reflect.get(obj1, key), Reflect.get(obj2, key)))
          resultType = false;
      } else {
        if (Reflect.get(obj1, key) !== Reflect.get(obj2, key)) resultType = false;
      }
    });
    return resultType;
  };
  
  /** 配置请求头headers */
  export const getConfigHeadrs = (options: object = {}) => {
    return { ...options, 'Content-Type': 'application/json; charset=utf-8' };
  };
  